home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / xlib03.zip / XMAIN.ASM < prev    next >
Assembly Source File  |  1993-04-05  |  34KB  |  1,091 lines

  1. ;-----------------------------------------------------------------------
  2. ; MODULE XMAIN
  3. ;
  4. ; Initialization, panning and split screen functions for all MODE X 256
  5. ; Color resolutions
  6. ;
  7. ; Compile with Tasm.
  8. ; C callable.
  9. ;
  10. ;
  11. ; ****** XLIB - Mode X graphics library                ****************
  12. ; ******                                               ****************
  13. ; ****** Written By Themie Gouthas                     ****************
  14. ; ****** Aeronautical Research Laboratory              ****************
  15. ; ****** Defence Science and Technology Organisation   ****************
  16. ; ****** Australia                                     ****************
  17. ;
  18. ; egg@dstos3.dsto.gov.au
  19. ; teg@bart.dsto.gov.au
  20. ;
  21. ; MODIFICATIONS:
  22. ;  26-9-92:       Pel panning code added
  23. ;-----------------------------------------------------------------------
  24.  
  25.  
  26. include xlib.inc
  27. include xmain.inc
  28.  
  29.  
  30.     .data
  31.  
  32.  
  33. ; Mode X CRTC register tweaks for various resolutions
  34.  
  35.  
  36.  
  37. X320Y200 label  word
  38.     db      0e3h    ; dot clock
  39.     db      02      ; Number of CRTC Registers to update
  40.     dw      00014h  ; turn off dword mode
  41.     dw      0e317h  ; turn on byte mode
  42.     dw      320     ; width
  43.     dw      200     ; height
  44.  
  45. X320Y240 label  word
  46.     db      0e3h    ; dot clock
  47.     db      10      ; Number of CRTC Registers to update
  48.     dw      00d06h  ; vertical total
  49.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  50.     dw      04109h  ; cell height (2 to double-scan)
  51.     dw      0ea10h  ; v sync start
  52.     dw      0ac11h  ; v sync end and protect cr0-cr7
  53.     dw      0df12h  ; vertical displayed
  54.     dw      00014h  ; turn off dword mode
  55.     dw      0e715h  ; v blank start
  56.     dw      00616h  ; v blank end
  57.     dw      0e317h  ; turn on byte mode
  58.     dw      320     ; width
  59.     dw      240     ; height
  60.  
  61. X360Y200 label  word
  62.     db      0e7h    ; dot clock
  63.     db      08      ; Number of CRTC Registers to update
  64.     dw      06b00h  ; horz total
  65.     dw      05901h  ; horz displayed
  66.     dw      05a02h  ; start horz blanking
  67.     dw      08e03h  ; end horz blanking
  68.     dw      05e04h  ; start h sync
  69.     dw      08a05h  ; end h sync
  70.     dw      00014h  ; turn off dword mode
  71.     dw      0e317h  ; turn on byte mode
  72.     dw      360     ; width
  73.     dw      200     ; height
  74.  
  75. X360Y240  label word
  76.     db      0e7h    ; dot clock
  77.     db      17      ; Number of CRTC Registers to update
  78.     dw    06b00h    ; horz total
  79.     dw    05901h    ; horz displayed
  80.     dw    05a02h    ; start horz blanking
  81.     dw    08e03h    ; end horz blanking
  82.     dw    05e04h    ; start h sync
  83.     dw    08a05h    ; end h sync
  84.     dw      00d06h  ; vertical total
  85.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  86.     dw      04109h  ; cell height (2 to double-scan)
  87.     dw      0ea10h  ; v sync start
  88.     dw      0ac11h  ; v sync end and protect cr0-cr7
  89.     dw      0df12h  ; vertical displayed
  90.     dw    02d13h    ; offset;
  91.     dw      00014h  ; turn off dword mode
  92.     dw      0e715h  ; v blank start
  93.     dw      00616h  ; v blank end
  94.     dw      0e317h  ; turn on byte mode
  95.     dw      360
  96.     dw      240
  97.  
  98. X320Y400 label  word
  99.     db      0e3h    ; dot clock
  100.     db      03      ; Number of CRTC Registers to update
  101.     dw    04009h    ; cell height
  102.     dw      00014h  ; turn off dword mode
  103.     dw      0e317h  ; turn on byte mode
  104.     dw      320     ; width
  105.     dw      400     ; height
  106.  
  107. X320Y480 label  word
  108.     db      0e3h    ; dotclock
  109.     db      10      ; Number of CRTC Registers to update
  110.     dw      00d06h  ; vertical total
  111.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  112.     dw      04009h  ; cell height (2 to double-scan)
  113.     dw      0ea10h  ; v sync start
  114.     dw      0ac11h  ; v sync end and protect cr0-cr7
  115.     dw      0df12h  ; vertical displayed
  116.     dw      00014h  ; turn off dword mode
  117.     dw      0e715h  ; v blank start
  118.     dw      00616h  ; v blank end
  119.     dw      0e317h  ; turn on byte mode
  120.     dw      320     ; width
  121.     dw      480     ; height
  122.  
  123. X360Y400 label  word
  124.     db      0e7h    ; dot clock
  125.     db      09      ; Number of CRTC Registers to update
  126.     dw      06b00h  ; horz total
  127.     dw      05901h  ; horz displayed
  128.     dw      05a02h  ; start horz blanking
  129.     dw      08e03h  ; end horz blanking
  130.     dw      05e04h  ; start h sync
  131.     dw      08a05h  ; end h sync
  132.     dw    04009h    ; cell height
  133.     dw      00014h  ; turn off dword mode
  134.     dw      0e317h  ; turn on byte mode
  135.     dw      360     ; width
  136.     dw      400     ; height
  137.  
  138. X360Y480  label word
  139.     db      0e7h
  140.     db      17
  141.     dw    06b00h    ; horz total
  142.     dw    05901h    ; horz displayed
  143.     dw    05a02h    ; start horz blanking
  144.     dw    08e03h    ; end horz blanking
  145.     dw    05e04h    ; start h sync
  146.     dw    08a05h    ; end h sync
  147.     dw    00d06h    ; vertical total
  148.     dw    03e07h    ; overflow
  149.     dw    04009h    ; cell height
  150.     dw    0ea10h    ; v sync start
  151.     dw    0ac11h    ; v sync end and protect cr0-cr7
  152.     dw    0df12h    ; vertical displayed
  153.     dw    02d13h    ; offset
  154.     dw    00014h    ; turn off dword mode
  155.     dw    0e715h    ; v blank start
  156.     dw    00616h    ; v blank end
  157.     dw    0e317h    ; turn on byte mode
  158.     dw      360
  159.     dw      480
  160.  
  161. LAST_X_MODE         equ    7
  162. ModeTable label word    ; Mode X tweak table
  163.     dw      offset X320Y200
  164.     dw      offset X320Y240
  165.     dw      offset X360Y200
  166.     dw      offset X360Y240
  167.     dw      offset X320Y400
  168.     dw      offset X320Y480
  169.     dw      offset X360Y400
  170.     dw      offset X360Y480
  171.  
  172. PARAMS label byte
  173.  
  174.     _CurrXMode               dw 0   ; Current graphics mode index
  175.     _InGraphics              db 0   ; Flag indicating graphics activity
  176.     _ScrnPhysicalByteWidth   dw 0   ; Logical width in bytes of screen
  177.     _ScrnPhysicalPixelWidth  dw 0   ; Logical width in pixels of screen
  178.     _ScrnPhysicalHeight      dw 0   ; Logical Height of screen
  179.     _ErrorValue              db 0   ; Set after function calls
  180.  
  181.  
  182.     _SplitScrnActive         db 0   ; Flag indicating Split scrn activity
  183.     _DoubleBufferActive      dw 0   ; Flag indicating double buffering
  184.  
  185.     _SplitScrnScanLine       dw 0   ; Split Screen's starting scan line
  186.     _SplitScrnVisibleHeight  dw 0   ; Split Screen's height on screen
  187.  
  188.     _SplitScrnOffs           dw 0   ; Offset in video ram of Split Screen
  189.                     ; always = 0
  190.     _Page0_Offs              dw 0   ; Ofset in video ram of Main virtual
  191.                     ; screen ( = 0 if no split screen
  192.                     ; otherwise = offset of first byte
  193.                     ; after split screen
  194.     _Page1_Offs              dw 0   ; Ofset in video ram of Second virtual
  195.                     ; screen ( = 0 if no split screen
  196.                     ; otherwise = offset of first byte
  197.                     ; after split screen
  198.                     ; = Page0_Offs if Doubble buffering
  199.                     ; not enabled
  200.     _NonVisual_Offs          dw 0   ; Ofset in video ram of first byte
  201.                     ; of non visible ram
  202.     _ScrnLogicalByteWidth    dw 0   ; Logical width in bytes of screen
  203.     _ScrnLogicalPixelWidth   dw 0   ; Logical width in pixels of screen
  204.     _ScrnLogicalHeight       dw 0   ; Logical Height of screen
  205.  
  206.     _MaxScrollX              dw 0   ; Max X start position of Physical
  207.                     ; screen within virtual screen (in
  208.                     ; bytes)
  209.     _MaxScrollY              dw 0   ; Max Y start position of Physical
  210.                     ; screen within virtual screen
  211.  
  212.     _VisiblePageIdx          dw 0   ; Index of currently visible D.B.
  213.                     ; page
  214.  
  215.     PageAddrTable label word
  216.     _VisiblePageOffs     dw 0   ; Table containing starting offsets
  217.     _HiddenPageOffs         dw 0   ; of the double buffer pages
  218.  
  219. PARAMS_END label byte
  220.  
  221. PARAM_COUNT equ ($-PARAMS)
  222.  
  223.  
  224. ; Index/data pairs for CRT Controller registers that differ between
  225. ; mode 13h and mode X.
  226.  
  227.  
  228.     .code
  229.  
  230.  
  231.     ;Pelpan values for 0,1,2,3 pixel panning to the left, respectively
  232.     PelPanMask              db      000h,002h,004h,006h
  233.  
  234.  
  235. DoubleScanFlag db ?     ; Flag to indicate double scanned mode
  236.  
  237.  
  238.  
  239. ;-------------------------------------------------------------------------
  240. ; Local Logical Screen Width setting function
  241. ; cx = Requitrd Logical Width
  242. ;
  243. ; WARNING: no registers are preserved
  244.  
  245. SetLogicalScrWidth proc
  246.     mov   dx,CRTC_INDEX
  247.     mov   al,CRTC_OFFSET
  248.     out   dx,al
  249.     inc   dx
  250.  
  251.     mov   ax,cx
  252.     cmp   ax,[_ScrnPhysicalPixelWidth]; Is logical width >= physical width
  253.     jge   @@ValidLogicalWidth          ; yes - continue
  254.     mov   ax,bx                        ; no - set logical width = physical
  255.  
  256. @@ValidLogicalWidth:
  257.     shr   ax,3
  258.     out   dx,al
  259.  
  260.     ; The EXACT logical pixel width may not have been possible since
  261.     ; it should be divisible by 8. Round down to the closest possible
  262.     ; width and update the status variables
  263.  
  264.     shl   ax,1
  265.     mov   bx,ax
  266.     mov   [_ScrnLogicalByteWidth],ax  ; Store the byte width of virtual
  267.                       ; screen
  268.     sub   ax,[_ScrnPhysicalByteWidth] ; Calculate and store Max X position
  269.     shl   ax,2                        ; of physical screen in virtual
  270.     mov   [_MaxScrollX],ax            ; screen in pixels
  271.     mov   ax,bx                       ; set ax to byte width of virt scrn
  272.     shl   ax,2                        ; convert to pixels
  273.     mov   [_ScrnLogicalPixelWidth],ax ; store virt scrn pixel width
  274.     mov   cx,ax                       ; save ax (return value)
  275.  
  276.     ; calculate no. non split screen rows in video ram
  277.  
  278.     mov   ax,0ffffh                ; cx = Maximum video ram offset
  279.     sub   dx,dx                    ; DX:AX is divide operand,  set DX = 0
  280.     div   bx                       ; divide ax by ScrnLogicalByteWidth
  281.     mov   [_ScrnLogicalHeight],ax  ; Save Screen Logical Height
  282.     sub   ax,[_ScrnPhysicalHeight] ; Update the maximum Y position of
  283.     mov   [_MaxScrollY],ax         ; Physical screen in logical screen
  284.     mov   ax,cx                    ; restore ax (return value)
  285.  
  286. @@Done: ret
  287. SetLogicalScrWidth endp
  288.  
  289.  
  290.  
  291.  
  292. ;-----------------------------------------------------------------------
  293. ; Mode X graphics mode set with a virtual screen
  294. ;   logical screen width.
  295. ; C near-callable as:
  296. ;
  297. ;    int x_set_mode(unsigned int mode,unsigned int WidthInPixels);
  298. ;
  299. ; returns the actual width of the allocated virtual screen in pixels
  300. ; if a valid mode was selected otherwise returns -1
  301. ;
  302. ; Saves virtual screen pixel width in _ScrnLogicalPixelWidth.
  303. ; Saves virtual screen byte  width in _ScrnLogicalByteWidth.
  304. ; Physical screen dimensions are set in _ScrnPhysicalPixelWidth,
  305. ; _ScrnPhysicalByteWidth and _ScrnPhysicalHeight
  306. ;
  307. ;
  308. ; Modes:  0  = 320 x 200  (256 color)
  309. ;      1  = 320 x 240  (256 color)
  310. ;         2  = 360 x 240  (256 color)
  311. ;         3  = 320 x 400  (256 color)
  312. ;      4  = 320 x 480  (256 color)
  313. ;         5  = 360 x 480  (256 color)
  314. ;
  315. ; Written by Themie Gouthas,
  316. ; parts adapted from M. Abrash code.
  317. ;------------------------------------------------------------------------
  318. _x_set_mode proc
  319.     ARG   mode:word,logicalscrwidth:word
  320.     push  bp      ;preserve caller's stack frame
  321.     mov   bp,sp
  322.  
  323.     push  si      ;preserve C register vars
  324.     push  di      ; (don't count on BIOS preserving anything)
  325.  
  326.     cld
  327.     mov   ax,ds
  328.     mov   es,ax
  329.     mov   di,offset PARAMS
  330.     xor   ax,ax
  331.     mov   cx,PARAM_COUNT
  332.     rep   stosb
  333.  
  334.     mov   cx,[mode]
  335.     cmp   cx,LAST_X_MODE        ; have we selected a valid mode
  336.     jle   @@ValidMode           ; Yes !
  337.  
  338.     mov   [_InGraphics],FALSE   ; No return -1
  339.     mov   ax,-1
  340.     pop   di
  341.     pop   si
  342.     pop   bp
  343.     ret
  344.  
  345. @@ValidMode:
  346.  
  347.     mov   [_CurrXMode],cx
  348.     mov   [_InGraphics],TRUE
  349.  
  350.     xor   al,al
  351.     cmp   cx,3
  352.     jg    @@SetDoubleScanFlag
  353.     mov   al,TRUE
  354. @@SetDoubleScanFlag:
  355.     mov   cs:[DoubleScanFlag],al
  356.  
  357.     mov   ax,13h                ; let the BIOS set standard 256-color
  358.     int   10h                   ;  mode (320x200 linear)
  359.  
  360.     mov   dx,SC_INDEX
  361.     mov   ax,0604h
  362.     out   dx,ax                 ; disable chain4 mode
  363.     mov   ax,0100h
  364.     out   dx,ax                 ; synchronous reset while setting Misc
  365.                     ;  Output for safety, even though clock
  366.                     ;  unchanged
  367.  
  368.     mov   bx,offset ModeTable
  369.     shl   cx,1
  370.     add   bx,cx
  371.     mov   si, word ptr [bx]
  372.     lodsb
  373.  
  374.     mov   dx,MISC_OUTPUT
  375.     out   dx,al               ; select the dot clock and Horiz
  376.                   ;  scanning rate
  377.     mov   dx,SC_INDEX
  378.     mov   ax,0300h
  379.     out   dx,ax               ; undo reset (restart sequencer)
  380.  
  381.  
  382.     mov   dx,CRTC_INDEX       ; reprogram the CRT Controller
  383.     mov   al,11h              ; VSync End reg contains register write
  384.     out   dx,al               ; protect bit
  385.     inc   dx                  ; CRT Controller Data register
  386.     in    al,dx               ; get current VSync End register setting
  387.     and   al,07fh             ; remove write protect on various
  388.     out   dx,al               ; CRTC registers
  389.     dec   dx                  ; CRT Controller Index
  390.     cld
  391.     xor   cx,cx
  392.     lodsb
  393.     mov   cl,al
  394.  
  395. @@SetCRTParmsLoop:
  396.     lodsw                     ; get the next CRT Index/Data pair
  397.     out   dx,ax               ; set the next CRT Index/Data pair
  398.     loop  @@SetCRTParmsLoop
  399.  
  400.     mov   dx,SC_INDEX
  401.     mov   ax,0f02h
  402.     out   dx,ax               ; enable writes to all four planes
  403.     mov   ax,SCREEN_SEG       ; now clear all display memory, 8 pixels
  404.     mov   es,ax               ; at a time
  405.     sub   di,di               ; point ES:DI to display memory
  406.     sub   ax,ax               ; clear to zero-value pixels
  407.     mov   cx,8000h            ; # of words in display memory
  408.     rep   stosw               ; clear all of display memory
  409.  
  410.  
  411.     ;  Set pysical screen dimensions
  412.  
  413.     lodsw                               ; Load scrn pixel width
  414.     mov   [_ScrnPhysicalPixelWidth],ax  ;  from tweak table and store
  415.     mov   [_SplitScrnScanLine],ax       ; No splitscrn ==
  416.                         ; splitscrn=PhysicalscrnHeight
  417.     mov   bx,ax                         ; Copy width for later use
  418.     shr   ax,2                          ; Convert to byte width
  419.     mov   [_ScrnPhysicalByteWidth],ax   ; Store for later use
  420.     lodsw                               ; Load Screen Phys. Height
  421.     mov   [_ScrnPhysicalHeight],ax      ; Store for later use
  422.  
  423.  
  424.     ;  Mode X is set, now set the required logical page width.
  425.  
  426.     mov     cx,[logicalscrwidth]
  427.  
  428.     call    SetLogicalScrWidth
  429.  
  430.     pop     di      ;restore C register vars
  431.     pop     si
  432.     pop     bp      ;restore caller's stack frame
  433.     ret
  434. _x_set_mode endp
  435.  
  436. ;----------------------------------------------------------------------
  437. ; Mode X (256 color mode) set default access video plane
  438. ;
  439. ; C near-callable as:
  440. ;    void x_select_default_plane(unsigned char plane);
  441. ;
  442. ; Enables Read/Write access to a plane using general memory access
  443. ; methods
  444. ;
  445. ; Written by Themie Gouthas
  446. ;----------------------------------------------------------------------
  447. _x_select_default_plane proc
  448. ARG Plane:byte
  449.         push bp
  450.     mov  bp,sp       ; set up stack frame
  451.         mov  cl,byte ptr [Plane]
  452.  
  453.         ; SELECT WRITE PLANE
  454.     and  cl,011b              ;CL = plane
  455.     mov  ax,0100h + MAP_MASK  ;AL = index in SC of Map Mask reg
  456.     shl  ah,cl                ;set only the bit for the required
  457.                   ; plane to 1
  458.     mov  dx,SC_INDEX          ;set the Map Mask to enable only the
  459.     out  dx,ax                ; pixel's plane
  460.  
  461.         ; SELECT READ PLANE
  462.         mov  ah,cl                ;AH = plane
  463.     mov  al,READ_MAP          ;AL = index in GC of the Read Map reg
  464.     mov  dx,GC_INDEX          ;set the Read Map to read the pixel's
  465.     out  dx,ax                ; plane
  466.  
  467.         pop  bp
  468.         ret
  469. _x_select_default_plane endp
  470.  
  471.  
  472. ;----------------------------------------------------------------------
  473. ; Mode X (256 color mode) Set Mode X split screen starting row
  474. ; The split screen resides on the bottom half of the screen and has a
  475. ; starting address of A000:0000
  476. ;
  477. ; C near-callable as:
  478. ;    void x_set_splitscreen(unsigned int line);
  479. ;
  480. ; Updates _Page0_Offs to reflect the existence of the split screen region
  481. ; ie _MainScrnOffset is set to the offset of the first pixel beyond the split
  482. ; screen region
  483. ;
  484. ; Written by Themie Gouthas
  485. ;----------------------------------------------------------------------
  486.  
  487. _x_set_splitscreen proc
  488.     ARG Line:word
  489.     push bp
  490.     mov  bp,sp       ; set up stack frame
  491.     push si
  492.  
  493.     xor  si,si       ; si=0 -> x virtual page start coord
  494.  
  495.     cmp  [_DoubleBufferActive],0
  496.     jne   @@error
  497.  
  498.     cmp  [_SplitScrnActive],0
  499.     je   @@NotPreviouslyCalled
  500.  
  501. @@error:
  502.     mov  [_ErrorValue],ERROR
  503.     pop  si
  504.     pop  bp          ; Return if previously called
  505.     ret
  506.  
  507. @@NotPreviouslyCalled:
  508.  
  509.     ; Turn on split screen pal pen suppression, so the split screen
  510.     ; wo'nt be subject to pel panning as is the non split screen portion.
  511.  
  512.     mov  dx,INPUT_STATUS_0
  513.     in   al,dx                  ; Reset the AC Index/Data toggle to
  514.                     ;  index state
  515.     mov  al,AC_MODE_CONTROL+20h ; Bit 5 set to prevent screen blanking
  516.     mov  dx,AC_INDEX        ; Point AC to Index/Data register
  517.     out  dx,al
  518.     inc  dx                     ; Point to AC Data reg (for reads only)
  519.     in   al,dx                  ; Get the current AC Mode Control reg
  520.     or   al,20h                 ; Enable split scrn Pel panning suppress.
  521.     dec  dx                     ; Point to AC Index/Data reg (for writes only)
  522.     out  dx,al                  ; Write the new AC Mode Control setting
  523.                     ;  with split screen pel panning
  524.                     ;  suppression turned on
  525.  
  526.  
  527.     mov  [_SplitScrnActive],TRUE
  528.     mov  ax,[Line]
  529.     jns  @@NotNeg    ; Check that Split Scrn start scan line is +ve
  530.  
  531.     mov  ax,0        ; Since -ve set to 0
  532.  
  533. @@NotNeg:
  534.     mov  [_SplitScrnScanLine],ax   ; save the scanline
  535.  
  536.     
  537.  
  538.     mov  cl,cs:[DoubleScanFlag]
  539.     shl  ax,cl            ; Mode X 200 and 240 line modes are actually
  540.                   ; 400 and 480 lines that are double scanned
  541.                   ; so for start scanline multiply required ModeX
  542.                   ; scan line by 2 if its a double scanned mode
  543.  
  544.     mov  bx,ax             ; save the scanline
  545.  
  546.  
  547.     WaitVsyncStart        ; wait for vertical retrace
  548.  
  549.     cli                   ; Dont allow register setting to be interrupted
  550.     mov  dx,CRTC_INDEX
  551.     mov  ah,bl
  552.     mov  al,LINE_COMPARE
  553.     out  dx,ax            ; Bits 7-0 of the split screen scan line
  554.  
  555.     mov  ah,bh
  556.     and  ah,1
  557.     mov  cl,4
  558.     shl  ah,cl
  559.     mov  al,OVERFLOW     ; Bit 4 of overflow register = Bit 8 of split
  560.     out  dx,al           ; screen scan line,
  561.     inc  dx              ; So using readability of VGA registers
  562.     in   al,dx           ; Read the OVERFLOW register, and set the
  563.     and  al, not 10h     ; bit corresponding to Bit 8 (above)
  564.     or   al,ah
  565.     out  dx,al
  566.  
  567.     dec  dx
  568.     mov  ah,bh
  569.     and  al,2
  570.     mov  cl,3
  571.     ror  ah,cl
  572.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  573.     out  dx,al             ; Bit 9 of split screen scan line
  574.     inc  dx                ; As we did before, update the apropriate
  575.     in   al,dx             ; bit without disturbing the rest
  576.     and  al, not 40h
  577.     or   al,ah
  578.     out  dx,al
  579.     sti                    ; Registers are set, so interrupts are safe
  580.  
  581.     mov  ax,[_ScrnPhysicalHeight]     ; Determine where the first byte
  582.     sub  ax,[_SplitScrnScanLine]      ; of the non split screen video ram
  583.     mov  [_SplitScrnVisibleHeight],bx ; starts and store it for reference
  584.  
  585.     mov  bx,[_ScrnLogicalByteWidth]
  586.     mul  bx
  587.     mov  [_Page0_Offs],ax
  588.     mov  [_Page1_Offs],ax
  589.  
  590.     ; calculate no. non split screen rows in video ram
  591.     mov  cx,0ffffh             ; cx = Maximum video ram offset
  592.     sub  cx,ax                 ; cx = cx - _Page0_Offs
  593.     xchg cx,ax                 ; swap cx and ax
  594.     sub  dx,dx                 ; DX:AX is divide operand,  set DX = 0
  595.     div  bx                    ; divide ax (prev cx) by
  596.                    ; ScrnLogicalByteWidth
  597.  
  598.     mov  [_ScrnLogicalHeight],ax     ; Save Screen Logical Height
  599.     sub  ax,[_SplitScrnScanLine]     ; Update the maximum Y position of
  600.     mov  [_MaxScrollY],ax             ; Physical screen in logical screen
  601.  
  602.     xchg cx,ax                    ; restore original ax (MainScrnOfs)
  603.     mov  bh,al                    ; Set the visible screen start address
  604.     mov  ch,ah                    ; to the top left corner of the virtual
  605.     jmp  short StartAddrEntry     ; screen
  606. _x_set_splitscreen     endp
  607.  
  608.  
  609. ;-----------------------------------------------------------------------
  610. ; Mode X (256 color mode) Page flip primer
  611. ; No clipping is performed.
  612. ; C near-callable as:
  613. ;
  614. ;    void x_page_flip(unsigned int x, unsigned int y);
  615. ;
  616. ; Swaps visible and hidden page offsets and then executes the SetStartAddr
  617. ; to achieve a page flip.
  618. ;
  619. ; SEE x_set_start_addr below
  620. ;
  621. ; Written by Themie Gouthas
  622. ;------------------------------------------------------------------------
  623.  
  624. _x_page_flip proc
  625.     ARG x:word,y:word
  626.     push  bp                  ;preserve caller's stack frame
  627.     mov   bp,sp               ;point to local stack frame
  628.     push  si
  629.  
  630.     mov  si,[x]
  631.     mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment
  632.     mul  [y]                            ; for Y
  633.     cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?
  634.     jne  PageFlipEntry1
  635.  
  636.     mov  bx,[_HiddenPageOffs]
  637.     xchg bx,[_VisiblePageOffs]          ; Swap the Page Offsete
  638.     xchg [_HiddenPageOffs],bx
  639.     xor  [_VisiblePageIdx],01h          ; Set the Visible page index
  640.     jmp  short PageFlipEntry2
  641. _x_page_flip endp
  642.  
  643.  
  644. ;-----------------------------------------------------------------------
  645. ; Mode X (256 color mode) Set Mode X non split screen start address
  646. ;   of logical screen.
  647. ; C near-callable as:
  648. ;
  649. ;    void x_set_start_addr(unsigned int x, unsigned int y);
  650. ;
  651. ; Params: StartOffset is offset of first byte of logical screen ram
  652. ;           (Useful if you want to double buffer by splitting your non
  653. ;            split screen video ram into 2 pages)
  654. ;        X,Y coordinates of the top left hand corner of the physical screen
  655. ;           within the logical screen
  656. ;           X must not exceed (Logical screen width - Physical screen width)
  657. ;           Y must not exceed (Logical screen height - Physical screen height)
  658. ;
  659. ;
  660. ; Written by Themie Gouthas,
  661. ; Parts addapted from M. Abrash code published in DDJ Mag.
  662. ;------------------------------------------------------------------------
  663. _x_set_start_addr proc
  664.     ARG x:word,y:word
  665.     push bp
  666.     mov  bp,sp
  667.     push si
  668.  
  669.     mov  si,[x]
  670.     mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment
  671.     mul  [y]                            ; for Y
  672.     cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?
  673.     je   @@PageResolution
  674. PageFlipEntry1:
  675.     add  ax,[_Page0_Offs]               ; no - add page 0 offset
  676.     jmp  short @@AddColumn
  677.  
  678. PageFlipEntry2:
  679.  
  680. @@PageResolution:
  681.     add  ax,[_VisiblePageOffs]          ; Add visible page offset
  682.  
  683. @@AddColumn:
  684.     mov  cx,si
  685.     shr  cx,2
  686.     add  ax,cx                          ; add the column offset for X
  687.     mov  bh,al                          ; setup CRTC start addr regs and
  688.                         ; values in word registers for
  689.     mov  ch,ah                          ; fast word outs
  690.  
  691. StartAddrEntry:
  692.     mov  bl,ADDR_LOW
  693.     mov  cl,ADDR_HIGH
  694.  
  695.  
  696.         mov  dx,INPUT_STATUS_0    ;Waitfor trailing edge of Vsync pulse
  697. @@WaitDE:
  698.     in   al,dx
  699.     test al,01h
  700.     jnz  @@WaitDE             ;display enable is active low (0 = active)
  701.  
  702.     mov  dx,CRTC_INDEX
  703.     mov  ax,bx
  704.     out  dx,ax                ;start address low
  705.     mov  ax,cx
  706.     out  dx,ax                ;start address high
  707.  
  708.         mov  dx,AC_INDEX
  709.     mov  al,PEL_PANNING+20h   ; Point the attribute controller to pel pan
  710.     out  dx,al                ; reg. Bit 5 also set to prevent blanking
  711.  
  712.     and  si,0003h             ; select pel pan register value for the
  713.     mov  al,cs:PelPanMask[si] ; required x coordinate
  714.     out  dx,al                ; load new Pel Pan setting.
  715.  
  716. ; Now wait for vertical sync, so the other page will be invisible when
  717. ; we start drawing to it.
  718.  
  719.         WaitVsyncStart
  720.  
  721. ;    mov  dx,INPUT_STATUS_0    ; Now wait for vertical sync, so the other
  722. ;@@WaitVS:                        ; page will be invisible when we start
  723. ;    in   al,dx                ; drawing to it.
  724. ;    test al,08h
  725. ;    jz   @@WaitVS  ;vertical sync is active high (1 = active)
  726.  
  727.     mov  [_ErrorValue],OK
  728.     pop  si
  729.     pop  bp
  730.     ret
  731. _x_set_start_addr  endp
  732.  
  733.  
  734. ;-----------------------------------------------------------------------
  735. ; Mode X (256 color mode) Mode X split screen hide
  736. ; C near-callable as:
  737. ;
  738. ;    void x_hide_splitscreen()
  739. ;
  740. ; Hides an existing split screen by setting its starting scan line to
  741. ; the last physical screen scan line
  742. ;
  743. ; WARNING: Only to be used if SplitScrnLine has been previously called
  744. ; WARNING: DO NOT USE with mode 4-7 (320x400-360x480). The memory for
  745. ;       the initial split screen is reserved and the size limitations
  746. ;       of these modes means any change in the split screen scan line
  747. ;          will encroach on the split screen ram
  748. ;
  749. ; Written by Themie Gouthas
  750. ;------------------------------------------------------------------------
  751.  
  752. _x_hide_splitscreen proc
  753.     push bp
  754.     mov  bp,sp
  755.  
  756.     cmp  [_SplitScrnActive],TRUE
  757.     je   @@SplitScreenEnabled
  758.  
  759. @@error:
  760.         mov  [_ErrorValue],ERROR
  761.     pop  bp
  762.     ret
  763.  
  764. @@SplitScreenEnabled:
  765.     cmp  [_CurrXMode],3          ; Do nothing for Modes > 2
  766.     jg   @@error
  767.     mov  bx,[_ScrnPhysicalHeight]
  768.  
  769.         mov  ax,[_ScrnLogicalHeight]
  770.     sub  ax,bx
  771.     mov  [_MaxScrollY],ax
  772.     xor  ax,ax
  773.     mov  [_SplitScrnVisibleHeight],ax
  774.  
  775.     mov  cl,cs:[DoubleScanFlag]  ; Compensate for double scanned modes
  776.     shl  bx,cl
  777.  
  778.     WaitVsyncStart               ; wait for vertical retrace
  779.  
  780.     cli                 ; Dont allow register setting to be interrupted
  781.     mov  dx,CRTC_INDEX
  782.     mov  ah,bl
  783.     mov  al,LINE_COMPARE
  784.     out  dx,ax        ; Bits 7-0 of the split screen scan line
  785.  
  786.     mov  ah,bh
  787.     and  ah,1
  788.     shl  ah,4
  789.     mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split
  790.     out  dx,al        ; screen scan line,
  791.     inc  dx           ; So using readability of VGA registers
  792.     in   al,dx        ; Read the OVERFLOW register, and set the
  793.     and  al, not 10h  ; bit corresponding to Bit 8 (above)
  794.     or   al,ah
  795.     out  dx,al
  796.  
  797.     dec  dx
  798.     mov  ah,bh
  799.     and  al,2
  800.     ror  ah,3
  801.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  802.     out  dx,al             ; Bit 9 of split screen scan line
  803.     inc  dx                ; As we did before, update the apropriate
  804.     in   al,dx             ; bit without disturbing the rest
  805.     and  al, not 40h
  806.     or   al,ah
  807.     out  dx,al
  808.     sti                  ; Registers are set, so interrupts are safe
  809.  
  810. @@done:
  811.     
  812.         mov  [_ErrorValue],OK
  813.     pop  bp
  814.     ret
  815. _x_hide_splitscreen endp
  816.  
  817. ;-----------------------------------------------------------------------
  818. ; Mode X (256 color mode) Mode X split screen show
  819. ; C near-callable as:
  820. ;
  821. ;    void x_show_splitscreen()
  822. ;
  823. ; Restores split screen start scan line to the initial split screen
  824. ; starting scan line as set by SplitScrnLine.
  825. ;
  826. ; WARNING: Only to be used if SplitScrnLine has been previously called
  827. ; WARNING: DO NOT USE with mode 4-7 (320x400-360x480). The memory for
  828. ;       the initial split screen is reserved and the size limitations
  829. ;       of these modes means any change in the split screen scan line
  830. ;          will encroach on the split screen ram
  831. ;          Update: Now disabled for these modes
  832. ;
  833. ; Written by Themie Gouthas
  834. ;------------------------------------------------------------------------
  835.  
  836.  
  837. _x_show_splitscreen proc
  838.     push bp
  839.     mov  bp,sp
  840.  
  841.     cmp  [_SplitScrnActive],TRUE
  842.     je   @@SplitScreenEnabled
  843.  
  844. @@error:
  845.         mov  [_ErrorValue],ERROR
  846.     pop  bp
  847.     ret
  848.  
  849. @@SplitScreenEnabled:
  850.     cmp  [_CurrXMode],3          ; Do nothing for Modes > 2
  851.     jg   @@error
  852.  
  853.     mov  bx,[_SplitScrnScanLine]
  854.     mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y
  855.     sub  ax,bx
  856.         mov  [_MaxScrollY],ax
  857.  
  858.     mov  ax,[_ScrnPhysicalHeight]
  859.     sub  ax,bx
  860.     mov  [_SplitScrnVisibleHeight],ax
  861.  
  862.     mov  cl,cs:[DoubleScanFlag]  ; Compensate for double scanned modes
  863.     shl  bx,cl
  864.     WaitVsyncStart               ; wait for vertical retrace
  865.  
  866.     cli                 ; Dont allow register setting to be interrupted
  867.     mov  dx,CRTC_INDEX
  868.     mov  ah,bl
  869.     mov  al,LINE_COMPARE
  870.     out  dx,ax        ; Bits 7-0 of the split screen scan line
  871.  
  872.     mov  ah,bh
  873.     and  ah,1
  874.     shl  ah,4
  875.     mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split
  876.     out  dx,al        ; screen scan line,
  877.     inc  dx           ; So using readability of VGA registers
  878.     in   al,dx        ; Read the OVERFLOW register, and set the
  879.     and  al, not 10h  ; bit corresponding to Bit 8 (above)
  880.     or   al,ah
  881.     out  dx,al
  882.  
  883.     dec  dx
  884.     mov  ah,bh
  885.     and  al,2
  886.     ror  ah,3
  887.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  888.     out  dx,al             ; Bit 9 of split screen scan line
  889.     inc  dx                ; As we did before, update the apropriate
  890.     in   al,dx             ; bit without disturbing the rest
  891.     and  al, not 40h
  892.     or   al,ah
  893.     out  dx,al
  894.     sti                  ; Registers are set, so interrupts are safe
  895.  
  896. @@Done:
  897.         mov  [_ErrorValue],0
  898.     pop  bp
  899.     ret
  900. _x_show_splitscreen endp
  901.  
  902.  
  903. ;-----------------------------------------------------------------------
  904. ; Mode X (256 color mode) Modify Mode X split screen starting scan line
  905. ; C near-callable as:
  906. ;
  907. ;    void x_adjust_splitscreen(unsigned int ScanLine)
  908. ;
  909. ; Sets the split screen start scan line to a new scan line. Valid scan lines
  910. ; are between the initial split screen starting scan line and the last
  911. ; physical screen scan line.
  912. ;
  913. ; WARNING: Only to be used if SplitScrnLine has been previously called
  914. ; WARNING: DO NOT USE with mode 4-7 (320x400-360x480). The memory for
  915. ;       the initial split screen is reserved and the size limitations
  916. ;       of these modes means any change in the split screen scan line
  917. ;          will encroach on the split screen ram
  918. ;          Update: Now disabled for these modes
  919. ;
  920. ;
  921. ; Written by Themie Gouthas
  922. ;------------------------------------------------------------------------
  923.  
  924.  
  925. _x_adjust_splitscreen proc
  926.     ARG   ScanLine
  927.     push bp
  928.     mov  bp,sp
  929.  
  930.     cmp  [_SplitScrnActive],TRUE
  931.     je   @@SplitScreenEnabled
  932.  
  933. @@error:
  934.         mov  [_ErrorValue],ERROR
  935.     pop  bp
  936.     ret
  937.  
  938. @@SplitScreenEnabled:
  939.     cmp  [_CurrXMode],3          ; Do nothing for Modes > 2
  940.     jg   @@error
  941.     mov  bx,[ScanLine]            ; Is the required starting scan line
  942.     cmp  bx,[_SplitScrnScanLine]  ; valid ?
  943.     js   @@Done                   ; No - Then do nothing
  944.  
  945. @@ValidScanLine:
  946.  
  947.         mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y
  948.     sub  ax,bx
  949.         mov  [_MaxScrollY],ax
  950.  
  951.     mov  ax,[_ScrnPhysicalHeight]
  952.     sub  ax,bx
  953.     mov  [_SplitScrnVisibleHeight],ax
  954.  
  955.  
  956.     mov  cl,cs:[DoubleScanFlag]   ; Compensate for double scanned modes
  957.     shl  bx,cl
  958.  
  959.     WaitVsyncStart      ; wait for vertical retrace
  960.  
  961.     cli                 ; Dont allow register setting to be interrupted
  962.  
  963.     mov  dx,CRTC_INDEX
  964.     mov  ah,bl
  965.     mov  al,LINE_COMPARE
  966.     out  dx,ax        ; Bits 7-0 of the split screen scan line
  967.  
  968.     mov  ah,bh
  969.     and  ah,1
  970.     shl  ah,4
  971.     mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split
  972.     out  dx,al        ; screen scan line,
  973.     inc  dx           ; So using readability of VGA registers
  974.     in   al,dx        ; Read the OVERFLOW register, and set the
  975.     and  al, not 10h  ; bit corresponding to Bit 8 (above)
  976.     or   al,ah
  977.     out  dx,al
  978.  
  979.     dec  dx
  980.     mov  ah,bh
  981.     and  al,2
  982.     ror  ah,3
  983.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  984.     out  dx,al             ; Bit 9 of split screen scan line
  985.     inc  dx                ; As we did before, update the apropriate
  986.     in   al,dx             ; bit without disturbing the rest
  987.     and  al, not 40h
  988.     or   al,ah
  989.     out  dx,al
  990.     sti                    ; Registers are set, so interrupts are safe
  991. @@Done:
  992.         mov  [_ErrorValue],OK
  993.     pop   bp
  994.     ret
  995. _x_adjust_splitscreen endp
  996.  
  997.  
  998.  
  999. ;-----------------------------------------------------------------------
  1000. ; Mode X (256 color mode) Enable DoubleBuffering on non split screen area
  1001. ; C near-callable as:
  1002. ;
  1003. ;    int x_set_doublebuffer(unsigned int PageHeight);
  1004. ;
  1005. ; Params: PageHeight is the height of the virtual screen to double buffer
  1006. ;         Returns the closest possible height to the specified.
  1007. ;
  1008. ; Sets up two double buffering virtual pages
  1009. ; GLOBAL variables set:
  1010. ;
  1011. ;      _Page1_Offs        Offset of second virtual page
  1012. ;      _NonVisual_Offs          Offset of first non visible video ram byte
  1013. ;      _DoubleBufferActive      Flag
  1014. ;      _PageAddrTable           Table of Double buffering pages start offsets
  1015. ;      _ScrnLogicalHeight       Logical height of the double buffering pages
  1016. ;
  1017. ;
  1018. ; Written by Themie Gouthas
  1019. ;------------------------------------------------------------------------
  1020.  
  1021.  
  1022. _x_set_doublebuffer proc
  1023.        ARG PageHeight:word
  1024.        push  bp
  1025.        mov   bp,sp
  1026.  
  1027.        cmp   [_DoubleBufferActive],0
  1028.        je    @@OkToContinue
  1029. @error:
  1030.        mov   [_ErrorValue],ERROR
  1031.        pop   bp
  1032.        ret
  1033.  
  1034. @@OkToContinue:
  1035.        mov   [_VisiblePageIdx],0     ; Set visible Page to 0
  1036.        mov   ax,[_ScrnLogicalHeight] ; Set Maximum D.B. Page height to
  1037.        shr   ax,1                    ;   _ScrnLogicalHeight / 2
  1038.  
  1039.        mov   bx,[PageHeight]         ; Is the require D.B. Page Height
  1040.        cmp   ax,bx                   ;  > the Maximum  D.B. Page Height ?
  1041.  
  1042.        js    @@InvalidHeight         ; no  - jump
  1043.        mov   ax,bx                   ; yes - Set the D.B. Page height to
  1044.                      ;       to the maximum allowed.
  1045.  
  1046. @@InvalidHeight:
  1047.        mov   [_ScrnLogicalHeight],ax    ; Update logical screen height to
  1048.                     ;  reflect the height of a D.B. page
  1049.        mov   dx,ax
  1050.        mul   [_ScrnLogicalByteWidth]    ; Calculate the offset of the second
  1051.        mov   cx,ax                    ;  D.B. Page in video ram
  1052.        mov   bx,[_Page0_Offs]
  1053.        mov   [_VisiblePageOffs],bx
  1054.  
  1055.        add   ax,bx
  1056.        mov   [_Page1_Offs],ax           ; Save it
  1057.        mov   [_HiddenPageOffs],ax
  1058.  
  1059.        add   ax,cx                      ; Calculate the offset of first byte
  1060.        mov   [_NonVisual_Offs],ax       ;  beyond the D.B. pages and save it
  1061.        mov   [_DoubleBufferActive],TRUE ; Set flag indicating D.B'ing mode on
  1062.  
  1063.        mov   ax,dx
  1064.        sub   ax,[_ScrnPhysicalHeight]
  1065.        add   ax,[_SplitScrnVisibleHeight]
  1066.        mov   [_MaxScrollY],ax
  1067.  
  1068.        mov   ax,dx                      ; return the D.B. pages' height
  1069.        mov   [_ErrorValue],OK
  1070.        pop   bp
  1071.        ret
  1072. _x_set_doublebuffer endp
  1073.  
  1074.  
  1075. ;----------------------------------------------------------------------
  1076. ; Return to text mode
  1077. ;
  1078. _x_text_mode proc
  1079.        push  bp
  1080.  
  1081.        mov   ax,03h        ; Restore Text Mode
  1082.        int   10h
  1083.  
  1084.        pop   bp
  1085.        ret
  1086. _x_text_mode endp
  1087.  
  1088.  
  1089.     end
  1090.  
  1091.